#include <mc/blocks.h>
#include <mc/blockImp.h>
#include <iostream>

namespace mc
{

//! @brief 工厂函数 
Block* BlockFactory::getBlock(BlockType type)
{
    switch (type)
    {
    case DIRT:
        return new Dirt();
    case STONE:
        return new Stone();
    case GRASS:
        return new Grass();
    case TNT:
        return new Tnt();
    case OAKLOG:
        return new OakLog();
    case PSITON:
        return new Piston();
    case CRAFTINGTABLE:
        return new CraftingTable();
    default:
        return nullptr;
    }
}

//! @brief 纹理文件宏定义
#define TEXTURE_FOLDER "block/"
#define TEXTURE_PATH(texName) (TEXTURE_FOLDER #texName ".png")
#define TOP_TEXTURE_PATH(texName) (TEXTURE_FOLDER #texName "_top.png")
#define SIDE_TEXTURE_PATH(texName) (TEXTURE_FOLDER #texName "_side.png")
#define BOTTOM_TEXTURE_PATH(texName) (TEXTURE_FOLDER #texName "_bottom.png")
#define FRONT_TEXTURE_PATH(texName) (TEXTURE_FOLDER #texName "_front.png")

//! @brief 加载方块纹理
void BlockFactory::loadAllBlockTextures()
{
    Dirt::_textures[0] = BlockImp::loadTexture(TEXTURE_PATH(dirt));

    Stone::_textures[0] = BlockImp::loadTexture(TEXTURE_PATH(stone));

    OakLog::_textures[0] = BlockImp::loadTexture(TOP_TEXTURE_PATH(oak_log));
    OakLog::_textures[1] = BlockImp::loadTexture(TOP_TEXTURE_PATH(oak_log));
    OakLog::_textures[2] = BlockImp::loadTexture(TEXTURE_PATH(oak_log));

    Grass::_textures[0] = BlockImp::loadTexture(TOP_TEXTURE_PATH(grass_block));
    Grass::_textures[1] = BlockImp::loadTexture(TEXTURE_PATH(dirt));
    Grass::_textures[2] = BlockImp::loadTexture(SIDE_TEXTURE_PATH(grass_block));

    Piston::_textures[0] = BlockImp::loadTexture(TOP_TEXTURE_PATH(piston));
    Piston::_textures[1] = BlockImp::loadTexture(BOTTOM_TEXTURE_PATH(piston));
    Piston::_textures[2] = BlockImp::loadTexture(SIDE_TEXTURE_PATH(piston));
    Tnt::_textures[0] = BlockImp::loadTexture(TOP_TEXTURE_PATH(tnt));
    Tnt::_textures[1] = BlockImp::loadTexture(BOTTOM_TEXTURE_PATH(tnt));
    Tnt::_textures[2] = BlockImp::loadTexture(SIDE_TEXTURE_PATH(tnt));
    CraftingTable::_textures[0] = BlockImp::loadTexture(TOP_TEXTURE_PATH(crafting_table));
    CraftingTable::_textures[1] = BlockImp::loadTexture(TEXTURE_PATH(oak_planks));
    CraftingTable::_textures[2] = BlockImp::loadTexture(FRONT_TEXTURE_PATH(crafting_table));
    CraftingTable::_textures[3] = BlockImp::loadTexture(SIDE_TEXTURE_PATH(crafting_table));
}

DECLARATION_TEXTURES(Dirt, 1);
DECLARATION_TEXTURES(Stone, 1);
DECLARATION_TEXTURES(OakLog, 3);
DECLARATION_TEXTURES(Grass, 3);
DECLARATION_TEXTURES(Piston, 3);
DECLARATION_TEXTURES(Tnt, 3);
DECLARATION_TEXTURES(CraftingTable, 4);

void Grass::draw()
{
    Block::shader.setVec4("backColor", glm::vec4(0.64f, 1.0f, 0.44f, 1.0f));
    BlockImp::drawInstantiation(this->_vaos[0], this->textures()[0], 6, this->_instanceMatrices.size());
    Block::shader.setVec4("backColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
    BlockImp::drawInstantiation(this->_vaos[1], this->textures()[1], 6, this->_instanceMatrices.size());
    BlockImp::drawInstantiation(this->_vaos[2], this->textures()[2], 24, this->_instanceMatrices.size());
}

}